// The code in this file collects lines of text from a given HTML node, or element.
// Calling sequence:
//      collectText(node) 
//      spliceText(text)
// The result is an array of assembled lines of text in the lines variable.

var text;  // list of text fragments
var lines;  // assembled lines of text

function spliceText(text) {
  // Create an array of lines, determined by newline characters.
  // Store it in the lines variable.
  lines = [];
  var i;  // index into text
  var fragment;  // element of text array
  var line = '';  // assembled text
  var blankLine = /^\s*$/;
  var hasNL = /[\r\n]/;
  var startsWithNL = /^\s*[\r\n](.*)/;
  var endsWithNL   = /(.*)[\r\n]\s*$/;
  var match;
  // We're ignoring newlines embedded in text.
  for (i = 0; i < text.length; i++) {
    fragment = text[i];
    if (blankLine.test(fragment)) {
      if (hasNL.test(fragment) && line) {
        lines.push(line);  // save assembled line
        line = '';
      }
      continue;
    }
    match = startsWithNL.exec(fragment);
    if (match) {
      if (line) {
        lines.push(line);  // save assembled line
        line = '';
      }
      fragment = match[1];
    }
    match = endsWithNL.exec(fragment);
    if (match) {
      line += match[1].trim();  // assemble
      lines.push(line);  // save assembled line
      line = fragment = '';
    }
    if (fragment) {
      line += fragment.trim();  // assemble
    }
  }
}

function collectText(node) {
  text = [];
  collectText0(node, text, '', 0);
}

function collectText0(node, text, margin, level) {
  //GM_log('node type ' + node.nodeType);
  var iChild;  // child index
  outer_switch: switch (node.nodeType) {
    case 3:  // text node
      text.push(node.data);
      break;
    case 1:  // element
      //GM_log('tag ' + node.tagName);
      switch (node.tagName) {
        case 'HEAD':
        case 'SCRIPT':
        case 'STYLE':
        case 'SELECT':
          break outer_switch;  // skip node
        case 'FRAME':
          //GM_log('document node type ' + node.contentDocument.nodeType);
          collectText0(node.contentDocument, text, margin + '    ');
          break outer_switch;  // skip frame after processing its document
      }
      if (1)  // collect text only, not element tags
        text.push('\n');
      else
        text.push('\n' + margin + '<' + node.tagName + '>');
      // fall through
    case 9:  // document
      for (iChild = 0; iChild < node.childNodes.length; iChild++)
        collectText0(node.childNodes[iChild], text, margin + '   ');
      break;
  }
}
